package com.jvm.reentrantlockp;

import java.util.concurrent.locks.ReentrantLock;

// ReentrantLock 是可重入锁
public class Demo4 {

    private static int num = 0;

    /**
     *
ReentrantLock 的使用过程：
创建锁：ReentrantLock lock = new ReentrantLock();
获取锁：lock.lock()
释放锁：lock.unlock();
     *
     */
    private static ReentrantLock lock = new ReentrantLock();

    private static void add() {
        /**
         *
         * 假如 ReentrantLock 是不可重入的锁，
         * 那么同一个线程第 2 次获取锁的时候由于前面的锁还未释放而导致死锁，
         * 程序是无法正常结束的。ReentrantLock 命名也挺好的 Re entrant Lock，
         * 和其名字一样，可重入锁。
         *
         * 注意
         *      1 lock()方法和 unlock()方法需要成对出现，锁了几次，也要释放几次，
                   否则后面的线程无法获取锁了；可以将 add 中的 unlock 删除一个事实，
                   上面代码运行将无法结束
                2 unlock()方法放在 finally 中执行，保证不管程序是否有异常，锁必定会释放
         */
        lock.lock();
        lock.lock();
        try {
            num++;
        } finally {
            // **lock.unlock()**一定要放在 finally 中，
            // 否则，若程序出现了异常，锁没有释放，那么其他线程就再也没有机会获取这个锁了。
            lock.unlock();
            lock.unlock();
        }

    }

    public static class T extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 10000; i++) {
                Demo4.add();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        T t1 = new T();
        T t2 = new T();
        T t3 = new T();

        t1.start();
        t2.start();
        t3.start();

        t1.join();
        t2.join();
        t3.join();

        System.out.println(Demo4.num);
    }

}
